﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using XSTDZ.ERP.Application.DataContracts;
using AutoMapper;
using XSTDZ.ERP.Domain.Models;
using XSTDZ.ERP.Core.Repositories;
using XSTDZ.ERP.Core.Generator;

namespace XSTDZ.ERP.Application.Implements
{
    public class ProfitAndLossBillServiceImpl : ApplicationServiceBase, IProfitAndLossBillService
    {
        IRepository<ProfitAndLossBill> _profitAndLossBillRepository;
        IRepository<ProfitAndLossBillDetail> _profitAndLossBillDetailRepository;
         IRepository<Stock> _stockRepository;
         public ProfitAndLossBillServiceImpl(IRepositoryContext repositoryContext, IRepository<ProfitAndLossBill> profitAndLossBillRepository, IRepository<ProfitAndLossBillDetail> profitAndLossBillDetailRepository, IRepository<Stock> stockRepository)
            : base(repositoryContext)
        {
            this._profitAndLossBillRepository = profitAndLossBillRepository;
            this._profitAndLossBillDetailRepository = profitAndLossBillDetailRepository;
           this._stockRepository = stockRepository;
        }

         public Guid AddProfitAndLossBill(ProfitAndLossBillDto profitAndLossBillDto)
         {
             var bill = Mapper.Map<ProfitAndLossBillDto, ProfitAndLossBill>(profitAndLossBillDto);
             bill.InitProfitAndLossBill();
             this._profitAndLossBillRepository.Add(bill);
             this.Context.Commit();
             return bill.Id;
         }

         internal Guid AddProfitAndLoss(ProfitAndLossBillDto profitAndLossBillDto, IEnumerable<ProfitAndLossBillDetailDto> profitAndLossBillDetailDtos)
         {
             var profitAndLossBill = Mapper.Map<ProfitAndLossBillDto, ProfitAndLossBill>(profitAndLossBillDto);
             var profitAndLossBillDetails = Mapper.Map<IEnumerable<ProfitAndLossBillDetailDto>, IEnumerable<ProfitAndLossBillDetail>>(profitAndLossBillDetailDtos);
             profitAndLossBill.InitProfitAndLossBill().AddDetails(profitAndLossBillDetails);
             this._profitAndLossBillRepository.Add(profitAndLossBill);
             return profitAndLossBill.Id;
         }
         public Guid AddProfitAndLossBill(ProfitAndLossBillDto profitAndLossBillDto, IEnumerable<ProfitAndLossBillDetailDto> profitAndLossBillDetailDtos)
         {
            var id= AddProfitAndLoss(profitAndLossBillDto, profitAndLossBillDetailDtos);
             this.Context.Commit();
             return id;
         }

         public Guid AddProfitAndLossBill(Guid profitAndLossBillId, IEnumerable<ProfitAndLossBillDetailDto> profitAndLossBillDetailDtos)
         {
             throw new NotImplementedException();
         }

         public void UpdateProfitAndLossBill(ProfitAndLossBillDto profitAndLossBillDto)
         {
             throw new NotImplementedException();
         }

         public void UpdateProfitAndLossBill(Guid profitAndLossBillId, IEnumerable<ProfitAndLossBillDetailDto> profitAndLossBillDetailDtos)
         {
             throw new NotImplementedException();
         }

         public void UpdateProfitAndLossBill(ProfitAndLossBillDto profitAndLossBillDto, IEnumerable<ProfitAndLossBillDetailDto> profitAndLossBillDetailDtos)
         {

             var profitAndLossBill = this._profitAndLossBillRepository.GetByKey(profitAndLossBillDto.Id);
             profitAndLossBillDto.CreateTime = profitAndLossBill.CreateTime;
             var targetBill = Mapper.Map(profitAndLossBillDto, profitAndLossBill);

             //处理明细
             var productCheckBillDetails = Mapper.Map<IEnumerable<ProfitAndLossBillDetailDto>, IEnumerable<ProfitAndLossBillDetail>>(profitAndLossBillDetailDtos);

             var updateItems = new List<ProfitAndLossBillDetail>();
             var insertItems = new List<ProfitAndLossBillDetail>();
             var itemIds = profitAndLossBill.ProfitAndLossBillDetail.Select(d => d.Id).Cast<Guid>();

             productCheckBillDetails.Each(
                 pd =>
                 {
                     if (itemIds.Contains(pd.Id))
                     {
                         updateItems.Add(pd);
                     }
                     else
                     {
                         insertItems.Add(pd.InitProfitAndLossBillDetail());
                     }
                 }
                 );
             if (updateItems.Count() != 0)
             {
                 foreach (var p in targetBill.ProfitAndLossBillDetail)
                 {
                     foreach (var m in updateItems)
                     {
                         if (m.Id == p.Id)
                         {
                             p.StockID = m.StockID;
                             p.Amount = m.Amount;
                             p.Remarks = m.Remarks;
                             break;
                         }
                     }
                 }

                 Mapper.Map(updateItems, targetBill.ProfitAndLossBillDetail);
             }
             if (insertItems.Count() != 0)
             {
                 this._profitAndLossBillDetailRepository.Add(insertItems);
             }
             this._profitAndLossBillRepository.Update(targetBill);
             this.Context.Commit();
         }

         public void ConvertProfitAndLossBillDeleteState(Guid profitAndLossBillId)
         {
             var pbill = this._profitAndLossBillRepository.GetByKey(profitAndLossBillId);
             pbill.Deleted = 1;
             pbill.ProfitAndLossBillDetail.Each(d => { d.Deleted = 1; });
             this._profitAndLossBillRepository.Update(pbill);
             this.Context.Commit();
         }

         public void ConvertProfitAndLossBillDeleteState(Guid profitAndLossBillId, IEnumerable<Guid> profitAndLossBillDetailIds)
         {
             var pbill = this._profitAndLossBillRepository.GetByKey(profitAndLossBillId);
             pbill.ProfitAndLossBillDetail.Each(d =>
             {
                 if (profitAndLossBillDetailIds.Contains(d.Id))
                 {
                     d.Deleted = 1;
                 }
             });
             this._profitAndLossBillRepository.Update(pbill);
             this.Context.Commit();
         }

         public ProfitAndLossBillDto GetProfitAndLossBill(Guid profitAndLossBillId)
         {
             var productCheckBill = this._profitAndLossBillRepository.GetByKey(profitAndLossBillId);
             if (productCheckBill.Checkor == null) { productCheckBill.Checkor = new User(); }; 
             return Mapper.Map<ProfitAndLossBill, ProfitAndLossBillDto>(productCheckBill);
         }

         public IEnumerable<ProfitAndLossBillDto> GetProfitAndLossBills(int pageIndex, int pageSize)
         {
             var orderby = new OrderByParameter<ProfitAndLossBill>(m => m.CreateTime, SortOrder.Descending);
             var productCheckBills = this._profitAndLossBillRepository.GetAll(pageIndex, pageSize, new[] { orderby });
             productCheckBills.Each(p => { if (p.Checkor == null) { p.Checkor = new User(); } });
            return  Mapper.Map<IEnumerable<ProfitAndLossBill>, IEnumerable<ProfitAndLossBillDto>>(productCheckBills);
             
             
         }

         public void AddProfitAndLossBillDetail(Guid productInBillId, ProfitAndLossBillDetailDto productCheckBillDetailDto)
         {
             throw new NotImplementedException();
         }

         public void UpdateProfitAndLossBillDetail(Guid productInBillId, IEnumerable<ProfitAndLossBillDetailDto> profitAndLossBillDetailDtos)
         {
             throw new NotImplementedException();
         }

         public ProfitAndLossBillDetailDto GetProfitAndLossBillDetail(Guid productCheckBillDetailId)
         {
             var productCheckBill = this._profitAndLossBillDetailRepository.GetByKey(productCheckBillDetailId);
             return Mapper.Map<ProfitAndLossBillDetail, ProfitAndLossBillDetailDto>(productCheckBill);
         }

         public IEnumerable<ProfitAndLossBillDetailDto> GetProfitAndLossBillDetails(Guid profitAndLossBillId)
         {
             var productCheckBills = this._profitAndLossBillDetailRepository.GetAll(d => d.ProfitAndLossBillID == profitAndLossBillId);
             return Mapper.Map<IEnumerable<ProfitAndLossBillDetail>, IEnumerable<ProfitAndLossBillDetailDto>>(productCheckBills);
         }


        //更新库存数据
         public void UpdateToStock(Guid profitAndLossBillId, IEnumerable<Guid> profitAndLossBillDetailIds)
         {
             var updateStocks = new List<Stock>();
             var pbill = this._profitAndLossBillRepository.GetByKey(profitAndLossBillId);
             pbill.ProfitAndLossBillDetail.Each(d =>
             {
                 if (profitAndLossBillDetailIds.Contains(d.Id))
                 {
                     updateStocks.Add(new Stock
                     {
                         Id = d.StockID,
                         StockCount = d.Amount //盈亏数量(正负表示，故直接操作)
                     });
                 }
             });
             if (updateStocks.Count() != 0)
             {
                 StockServiceImpl stockServiceImpl = new StockServiceImpl(this.Context, this._stockRepository);
                 stockServiceImpl.UpdateStockWithNoAdd(updateStocks);//更新库存
                 this.Context.Commit();
             }
         }
         private void UpdateToStock(Guid profitAndLossBillId, bool isCommit)
         {
             var updateStocks = new List<Stock>();
             var pbill = this._profitAndLossBillRepository.GetByKey(profitAndLossBillId);
             pbill.ProfitAndLossBillDetail.Each(d =>
             {
                     updateStocks.Add(new Stock
                     {
                         Id = d.StockID,
                         StockCount = d.Amount //盈亏数量(正负表示，故直接操作)
                     });
             });
             if (updateStocks.Count() != 0)
             {
                 StockServiceImpl stockServiceImpl = new StockServiceImpl(this.Context, this._stockRepository);
                 stockServiceImpl.UpdateStockWithNoAdd(updateStocks);//更新库存
                 if (isCommit)
                 {
                     this.Context.Commit();
                 }
             }
         }
        
        //审核
         public void Audit(Guid profitAndLossBillId, Guid UserID,bool isOk)
         {
             var pbill = this._profitAndLossBillRepository.GetByKey(profitAndLossBillId);
             if (pbill.BillState==1&&pbill.CheckState != 1)//未审核
             {
                 pbill.CheckorID = UserID;
                 pbill.CheckTime = DateTime.Now;
                 pbill.CheckState = isOk?1:2;
                 _profitAndLossBillRepository.Update(pbill);
                 if (isOk)//审核通过才扣库存
                 {
                     UpdateToStock(profitAndLossBillId, false);//更新库存
                 }
                 this.Context.Commit();
             }

         }
         public void Confirm(Guid profitAndLossBillId, Guid UserID)
         {
             var pbill = this._profitAndLossBillRepository.GetByKey(profitAndLossBillId);
             if (pbill.BillState != 1)//未提交
             {
                 pbill.UpdateID = UserID;
                 pbill.UpdateDate = DateTime.Now;
                 pbill.BillState = 1;
                 _profitAndLossBillRepository.Update(pbill);
                 UpdateToStock(profitAndLossBillId, false);//更新库存
                 this.Context.Commit();
             }
         }

         public string GetMaxBillNo()
         {
             var orderby = new OrderByParameter<ProfitAndLossBill>(m => m.CreateTime, SortOrder.Descending);
             var billNo = this._profitAndLossBillRepository.GetAll(1, 1, new[] { orderby }).FirstOrDefault();
             return billNo == null ? string.Empty : billNo.ProfitAndLossNo;
         }
    }

}
